package com.javaframe.role.dao.core;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.springframework.stereotype.Repository;

import com.javaframe.role.tools.GenericsUtils;
import com.javaframe.role.tools.PageInfo;

/**
 * 负责为单个Entity对象提供CRUD操作的Hibernate DAO基类. 
 * 子类只要在类定义时指定所管理Entity的Class, 即拥有对单个Entity对象的CRUD操作.
 * 
 * @see HibernateGenericDao
 * @author Victor Von
 */
@Repository
public class HibernateEntityDao<T> extends HibernateGenericDao implements
		EntityDao<T> {

	/** DAO所管理的Entity类型. */
	protected Class<T> entityClass; 

	/**
	 * 在构造函数中将泛型T.class赋给entityClass.
	 */
	public HibernateEntityDao() {
		entityClass = GenericsUtils.getSuperClassGenricType(getClass());
	}

	/**
	 * 取得entityClass.JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重载此函数达到相同效果。
	 */
	protected Class<T> getEntityClass() {
		return entityClass;
	}

	/**
	 * 根据ID获取对象.
	 * 
	 * @see HibernateGenericDao#getId(Class,Object)
	 */
	public T get(Serializable id) {
		return get(getEntityClass(), id);
	}

	/**
	 * 获取全部对象
	 * 
	 * @see HibernateGenericDao#getAll(Class)
	 */
	public List<T> getAll() {
		return getAll(getEntityClass());
	}
	/**
	 * 获取全部对象并进行分页
	 * 
	 * @see HibernateGenericDao#getAll(Class)
	 */
	public List<T> getAll(String hql,List<?> list,PageInfo page) {	
		if (hql == null || hql.trim().equals("")) {
	         throw new IllegalArgumentException(
	               "Null name or empty name is found, cannot perform getNamedQueryData(String s) function.");
	      }
		Query query=getSession().createQuery(hql);
		if (list != null) {
           int i = 0;
           for (Iterator<?> it = list.iterator(); it.hasNext();) {
             query.setParameter(i++, it.next());
           }
        }
		if (page == null) {
	        return query.list();
	    }else{
			int total = -1;  
	        if (null != page && page.getPageSize() > 0) {
	           total = query.list().size();
	           query.setFirstResult((page.getPageNo() - 1) * page.getPageSize());
	           query.setMaxResults(page.getPageSize());
		    }else{		    	    
	           page.setPageNo(0);
	           query.setFirstResult(0);
	           query.setMaxResults(page.getPageSize());	         
	        }     
	        page.setTotalCount(total);
	        page.setTotalPage(total / page.getPageSize() + (total % page.getPageSize() != 0 ? 1 : 0));
	        return query.list();
		}	
	}
	/**
	 * 获取全部对象,带排序参数.
	 * 
	 * @see HibernateGenericDao#getAll(Class,String,boolean)
	 */
	public List<T> getAll(String orderBy, boolean isAsc) {
		return getAll(getEntityClass(), orderBy, isAsc);
	}

	/**
	 * 根据ID移除对象.
	 * 
	 * @see HibernateGenericDao#removeById(Class,Serializable)
	 */
	public void removeById(Serializable id) {
		removeById(getEntityClass(), id);
	}

	/**
	 * 根据ID移除对象.
	 * 
	 * @see HibernateGenericDao#removeById(Class,Serializable)
	 */
	public void removeByMap(Map<?,?> map) {
		String temp ="0";
		List<?> items=new ArrayList<T>();
		items=(List<?>)map.get("items");
		final int size=items.size();
		Object[] ids=new Object[size];
		String identifier=map.get("identifier").toString();
		String table=map.get("table").toString();
		for (int i=0;i<size;i++){
			//ids[i]=Long.valueOf(((Map<?, ?>)items.get(i)).get(identifier).toString());  
			ids[i]=((Map<?, ?>)items.get(i)).get(identifier); 
		}
		for (Object id:ids){
			temp += ",?";
		}
		//getHibernateTemplate().bulkUpdate("update "+table+" set deleted = 1 where "+identifier+" in ("+temp+")",ids);
		getHibernateTemplate().bulkUpdate("update "+table+" set deleted = 1 where userId in ("+temp+")",ids);
	}
	/**
	 * 取得Entity的Criteria.
	 * 
	 * @see HibernateGenericDao#createCriteria(Class,Criterion[])
	 */
	public Criteria createCriteria(Criterion... criterions) {
		return createCriteria(getEntityClass(), criterions);
	}

	/**
	 * 取得Entity的Criteria,带排序参数.
	 * 
	 * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[])
	 */
	public Criteria createCriteria(String orderBy, boolean isAsc,
			Criterion... criterions) {
		return createCriteria(getEntityClass(), orderBy, isAsc, criterions);
	}

	/***************************************************************************
	 * 根据属性名和属性值查询对象。属性字段数组长度必须登录值数组
	 * 
	 * @return 符合条件的对象列表
	 */
	public List<T> findBy(String[] propertyNames, Object[] values) {
		return findBy(getEntityClass(), propertyNames, values);
	}

	/**
	 * 根据属性名和属性值查询对象.
	 * 
	 * @return 符合条件的对象列表
	 * @see HibernateGenericDao#findBy(Class,String,Object)
	 */
	public List<T> findBy(String propertyName, Object value) {
		return findBy(getEntityClass(), propertyName, value);
	}

	/**
	 * 根据属性名和属性值查询对象,带排序参数.
	 * 
	 * @return 符合条件的对象列表
	 * @see HibernateGenericDao#findBy(Class,String,Object,String,boolean)
	 */
	public List<T> findBy(String propertyName, Object value, String orderBy,
			boolean isAsc) {
		return findBy(getEntityClass(), propertyName, value, orderBy, isAsc);
	}

	/**
	 * 根据属性名和属性值查询单个对象.
	 * 
	 * @return 符合条件的唯一对象 or null
	 * @see HibernateGenericDao#findUniqueBy(Class,String,Object)
	 */
	public T findUniqueBy(String propertyName, Object value) {
		return findUniqueBy(getEntityClass(), propertyName, value);
	}

	/**
	 * 判断对象某些属性的值在数据库中唯一.
	 * 
	 * @param uniquePropertyNames
	 *            在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
	 * @see HibernateGenericDao#isUnique(Class,Object,String)
	 */
	public boolean isUnique(Object entity, String uniquePropertyNames) {
		return isUnique(getEntityClass(), entity, uniquePropertyNames);
	}
}

